<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<meta http-equiv="X-UA-Compatible" content="IE=edge">
	<title>虚拟dom</title>
	<link rel="stylesheet" href="">
</head>
<body>
	<div id="app" class="main">
		<h1 title="虚拟dom">虚拟dom</h1>
		<ul>
			<li>hello</li>
			<li>world</li>
		</ul>
	</div>
</body>
<script>
	
/* 虚拟dom
	
	1. 为什么使用虚拟dom
		如果不使用虚拟dom， 那么我们就要直接操作真实的dom，只要涉及到对真实dom的操作，那么就会有性能的损失。我们可以对真实的dom操作转换为对虚拟dom的操作，从而提高性能。

	2. 虚拟dom应该包含的基本属性
		元素结点：  {tag: div/ul/li...}
		文本结点: 	{tag: undefined, value: 'hello,world'}
		属性结点： 	{tag: div/ul/li..., data: {class: 'app', id: 'app'}}
		子元素： 	{tag: div/ul/li..., children: [{tag: div}, {tag: li}...]}

	3. 算法实现
		使用递归遍历真实的dom
*/


	// 虚拟dom对应的类结构
	class vNode {
		constructor(name, type, value, data) {
			this.name = name;	// 标签名
			this.type = type;
			this.value = value;
			this.data = data;
			this.children = [];		// 存在递归的操作，所以不方便直接传入
		}
	}



	// 开始遍历dom
	// 1. 获取dom根节点
	let dom = document.querySelector('#app');

	// 2. 开始定义递归函数
	function createNode(dom) {
		let vnode = null;	// 虚拟dom对象
		let name = dom.tagName && dom.tagName.toLowerCase() || 'text';
		let type = dom.nodeType;
		let value = dom.nodeValue;
		
		if (type === 1) {	// 元素结点
			let children = dom.childNodes;
			let data = dom.attributes;	// 返回伪数组
			data = Array.from(data).map(item=>{
				return {[item.nodeName]: item.nodeValue};
			});

			vnode = new vNode(name, type, undefined, data);

			// 元素结点可能存在子元素
			for (let i = 0; i < children.length; i++) {
				// 使用递归， 将子元素插入vNode中
				vnode.children.push(createNode(children[i]));
			}
		}
		else if (type === 3) {	// 文本结点
			vnode = new vNode(name, type, value, undefined);
		}

		return vnode;
	}
	let vnode = createNode(dom);


	/* 总结 
	
		1. 已经实现了极简化的虚拟dom的创建

		2. 存在的问题
			-1 现在需要提供 将虚拟dom转换为真实的dom 的算法
	*/


</script>
</html>
